/***************************************************************************
*   Copyright (C) 2008 by Chris Bornholdt,,,   *
*   chris.bornholdt@gmail.com   *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/

#ifndef _AREA_ITERATOR_HPP_
#define _AREA_ITERATOR_HPP_

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/call_traits.hpp>
#include <boost/concept_check.hpp>

template<bool Constant, bool RowMajor, bool Synch, bool Reverse>
class area_iterator : public boost::iterator_adaptor<
	area_iterator<Constant, RowMajor, Synch, Reverse>,
	typename mpl::if_c<Constant, typename storage_type::const_iterator, 
	typename storage_type::iterator>::type, boost::use_default, boost::random_access_traversal_tag>
{
	struct enabler{};
	struct disabler{};
	
	public:
		typedef typename boost::call_traits<typename area_iterator::base_type>::
			param_type base_param_type;
			
		friend class area_iterator<true, true, true, true>;
		friend class area_iterator<true, true, true, false>;
		friend class area_iterator<true, true, false, true>;
		friend class area_iterator<true, true, false, false>;
		
		friend class area_iterator<true, false, true, true>;
		friend class area_iterator<true, false, true, false>;
		friend class area_iterator<true, false, false, true>;
		friend class area_iterator<true, false, false, false>;
		
		friend class area_iterator<false, true, true, true>;
		friend class area_iterator<false, true, true, false>;
		friend class area_iterator<false, true, false, true>;
		friend class area_iterator<false, true, false, false>;
		
		friend class area_iterator<false, false, true, true>;
		friend class area_iterator<false, false, true, false>;
		friend class area_iterator<false, false, false, true>;
		friend class area_iterator<false, false, false, false>;
	
		area_iterator(base_param_type start, std::size_t width, std::size_t height, std::size_t row_stride)
			: area_iterator::iterator_adaptor_(start), width_(width), height_(height), 
				row_stride_(row_stride), x_(0), y_(0), start_(start) {}
				
		area_iterator(base_param_type start, std::size_t width, std::size_t height, std::size_t row_stride, 
			int x, int y) : area_iterator::iterator_adaptor_(start + x + y * row_stride), 
			width_(width), height_(height), row_stride_(row_stride), x_(x), y_(y), start_(start)
		{
			assert(0 <= index1() && index1() < (int)size1());	
				//use assert as I do not rebound/realign for performance reasons
		}
		
		template<bool C, bool M, bool S, bool R>
		area_iterator(const area_iterator<C, M, S, R>& other, typename boost::enable_if_c<
			Constant || !C, enabler>::type enable = enabler()) : area_iterator::iterator_adaptor_(other), 
			width_(other.width_), height_(other.height_), row_stride_(other.row_stride_), 
			x_(other.x_), y_(other.y_), start_(other.start_) {}
			
		area_iterator(){}
			
		
		int x() const	{	return x_;	}
		int y() const	{	return y_;	}
		std::size_t width() const	{	return width_;	}
		std::size_t height() const	{	return height_;	}
		
		area_iterator begin() const	{	return *this;	}
		area_iterator end() const	{	return end_area();	}
			
		Element& operator[](int x)
		{	return *(*this + x);	}
		const Element& operator[](int x) const
		{	return *(*this + x);	}
		
		
		void move(int d1, int d2)
		{
			assert(0 <= index1() + d1 && index1() + d1 < size1());
			assert(0 <= index2() + d2 && index2() + d2 < size2());
			
			index1() += d1;
			index2() += d2;
			realign();
		}
		
		void moveTo(int x, int y)
		{
			assert(0 <= index1() && index1() < size1());
			assert(-1 <= index2() && index2() <= size2());
			x_ = x;
			y_ = y;
			realign();
		}
		
		template<bool C, bool M, bool S, bool R>
		bool operator==(const area_iterator<C, M, S, R>& other) const
		{	return &(**this) == &(*other);	}
		
		template<bool C, bool M, bool S, bool R>
		int operator-(const area_iterator<C, M, S, R>& other) const
		{	return other.distance_to(*this);	}
		
		area_iterator begin_area() const
		{	return area_iterator(start_, width_, height_, row_stride_);		}
		
		area_iterator end_area() const
		{	return area_iterator(start_, width_, height_, row_stride_, width_ - 1, height_);	}
			
		//QUESTION what should area operations do when the current position is outside the new area
		
		//QUESTION   should resize take size in absolute or index coordinates
		area_iterator resize(std::size_t width, std::size_t height)
		{
			assert(width_ <= row_stride_);
			
			area_iterator returnValue(*this);
			returnValue.width_ = width;
			returnValue.height_ = height;
			
			return returnValue;
		}
			
		area_iterator strip() const
		{
			area_iterator returnValue(*this);
			
			returnValue.size2() = 1;
			returnValue.start_ += returnValue.index2() * returnValue.index2_stride();
			returnValue.index2() = 0;
			
			return returnValue;
		}
				
		area_iterator<Constant, !RowMajor, Synch, Reverse> transpose() const;
		area_iterator<Constant, RowMajor, !Synch, Reverse> flip() const;
		area_iterator reverse() const;	
		
		
		friend class major_wrapper;
		friend class minor_wrapper;
		class major_wrapper
		{
			public:
				major_wrapper(area_iterator& iter) : iter_(iter) {}
				
				area_iterator operator++(int n)
				{
					area_iterator return_iter(iter_);
					increment(mpl::bool_<Reverse>());
					assert(0 <= iter_.index1() && iter_.index1() < iter_.size1());
					iter_.realign();
					return return_iter;
				}
				area_iterator operator--(int n)
				{
					area_iterator return_iter(iter_);
					decrement(mpl::bool_<Reverse>());
					assert(0 <= iter_.index1() && iter_.index1() < iter_.size1());
					iter_.realign();
					return return_iter;
				}
				area_iterator& operator+=(int n)
				{
					increment(n, mpl::bool_<Reverse>());
					assert(0 <= iter_.index1() && iter_.index1() < iter_.size1());
					iter_.realign();
					return iter_;
				}
				area_iterator& operator-=(int n)
				{
					decrement(n, mpl::bool_<Reverse>());
					assert(0 <= iter_.index1() && iter_.index1() < iter_.size1());
					iter_.realign();
					return iter_;
				}	
				const area_iterator& operator=(int n)
				{
					set(n, mpl::bool_<Reverse>());
					assert(0 <= iter_.index1() && iter_.index1() < iter_.size1());
					iter_.realign();
					return iter_;
				}
				
				operator int() const	{	return iter_.index1();	}
			
			private:
				void increment(mpl::true_)
				{	iter_.index1()--;		}
				void increment(mpl::false_)
				{	iter_.index1()++;		}
				void decrement(mpl::true_)
				{	iter_.index1()++;		}
				void decrement(mpl::false_)
				{	iter_.index1()--;		}
				void increment(int n, mpl::true_)
				{	iter_.index1() -= n;	}
				void increment(int n, mpl::false_)
				{	iter_.index1() += n;	}
				void decrement(int n, mpl::true_)
				{	iter_.index1() += n;	}
				void decrement(int n, mpl::false_)
				{	iter_.index1() -= n;	}
				void set(int n, mpl::true_)
				{	iter_.index1() = iter_.size1() - 1 - n;	}
				void set(int n, mpl::false_)
				{	iter_.index1() = n;	}
					
				area_iterator& iter_;
		};
		
		class minor_wrapper
		{
			public:
				minor_wrapper(area_iterator& iter) : iter_(iter) {}
				
				area_iterator operator++(int n)
				{
					area_iterator return_iter(iter_);
					increment(mpl::bool_<Reverse ^ !Synch>());
					assert(0 <= iter_.index2() && iter_.index2() < iter_.size2());
					iter_.realign();
					return return_iter;
				}
				area_iterator operator--(int n)
				{
					area_iterator return_iter(iter_);
					decrement(mpl::bool_<Reverse ^ !Synch>());
					assert(0 <= iter_.index2() && iter_.index2() < iter_.size2());
					iter_.realign();
					return return_iter;
				}
				area_iterator& operator+=(int n)
				{
					increment(n, mpl::bool_<Reverse ^ !Synch>());
					assert(0 <= iter_.index2() && iter_.index2() < iter_.size2());
					iter_.realign();
					return iter_;
				}
				area_iterator& operator-=(int n)
				{
					decrement(n, mpl::bool_<Reverse ^ !Synch>());
					assert(0 <= iter_.index2() && iter_.index2() < iter_.size2());
					iter_.realign();
					return iter_;
				}	
				area_iterator& operator=(int n)
				{	
					set(n, mpl::bool_<Reverse ^ !Synch>());
					assert(0 <= iter_.index2() && iter_.index2() < iter_.size2());
					iter_.realign();
					return iter_;
				}
				
				operator int() const	{	return iter_.index2();	}
	
			private:
				void increment(mpl::true_)
				{	iter_.index2()--;		}
				void increment(mpl::false_)
				{	iter_.index2()++;		}
				void decrement(mpl::true_)
				{	iter_.index2()++;		}
				void decrement(mpl::false_)
				{	iter_.index2()--;		}
				void increment(int n, mpl::true_)
				{	iter_.index2() -= n;	}
				void increment(int n, mpl::false_)
				{	iter_.index2() += n;	}
				void decrement(int n, mpl::true_)
				{	iter_.index2() += n;	}
				void decrement(int n, mpl::false_)
				{	iter_.index2() -= n;	}
				void set(int n, mpl::true_)
				{	iter_.index2() = iter_.size1() - 1 - n;	}
				void set(int n, mpl::false_)
				{	iter_.index2() = n;	}
			
				area_iterator& iter_;
		};
		
		major_wrapper& major();
		int major() const;
		
		minor_wrapper& minor();
		int minor() const;			
		
	protected:
		friend class boost::iterator_core_access;
	
		//typedefs for readability
		typedef mpl::true_ RowMajorTrue;
		typedef mpl::false_ RowMajorFalse;
		typedef mpl::true_ SynchTrue;
		typedef mpl::false_ SynchFalse;
		typedef mpl::true_ ReverseTrue;
		typedef mpl::false_ ReverseFalse;
		
	
		inline int& index1()			{	return index1(mpl::bool_<RowMajor>());	}
		inline const int& index1() const	{	return index1(mpl::bool_<RowMajor>());	}
		inline int& index1(RowMajorTrue)			{	return x_;	}
		inline const int& index1(RowMajorTrue) const	{	return x_;	}
		inline int& index1(RowMajorFalse)		{	return y_;	}
		inline const int& index1(RowMajorFalse) const	{	return y_;	}
		
		inline int& index2()			{	return index2(mpl::bool_<RowMajor>());	}
		inline const int& index2() const	{	return index2(mpl::bool_<RowMajor>());	}
		inline int& index2(RowMajorTrue)			{	return y_;	}
		inline const int& index2(RowMajorTrue) const	{	return y_;	}
		inline int& index2(RowMajorFalse)		{	return x_;	}
		inline const int& index2(RowMajorFalse) const	{	return x_;	}
		
		inline std::size_t& size1()			{	return size1(mpl::bool_<RowMajor>());	}
		inline std::size_t size1() const		{	return size1(mpl::bool_<RowMajor>());	}
		inline std::size_t& size1(RowMajorTrue)				{	return width_;	}
		inline std::size_t size1(RowMajorTrue) const		{	return width_;	}
		inline std::size_t& size1(RowMajorFalse)				{	return height_;	}
		inline std::size_t size1(RowMajorFalse) const		{	return height_;	}
		
		inline std::size_t& size2()			{	return size2(mpl::bool_<RowMajor>());	}
		inline std::size_t size2() const	{	return size2(mpl::bool_<RowMajor>());	}
		inline std::size_t& size2(RowMajorTrue)				{	return height_;	}
		inline std::size_t size2(RowMajorTrue) const		{	return height_;	}
		inline std::size_t& size2(RowMajorFalse)				{	return width_;	}
		inline std::size_t size2(RowMajorFalse) const		{	return width_;	}
	
		inline std::size_t stride1()	{	return stride1(mpl::bool_<RowMajor>());	}
		inline std::size_t stride2()	{	return stride2(mpl::bool_<RowMajor>());	}
		inline std::size_t stride1(RowMajorTrue)			{	return 1;	}
		inline std::size_t stride1(RowMajorFalse)		{	return row_stride_;	}
		inline std::size_t stride2(RowMajorTrue)			{	return row_stride_;	}
		inline std::size_t stride2(RowMajorFalse)		{	return 1;	}
		
		/*	decide equality using x and y values, this will prevent certain equality when
			and end of area iterator overlaps with the valid area (when width == row_stride)	*/
		bool equal(const area_iterator& other) const
		{	return (other.x_ == x_) && (other.y_ == y_);		}
		
		template<typename Iter>
		bool equal(const Iter& other) const
		{	return &(*other) == &(**this);	}
		
		void increment()	//equivalent to index1()++, but with proper side effects
		{	_increment(mpl::bool_<Reverse>());	}
		
		inline void _increment(ReverseTrue)	{	_decrement(ReverseFalse());	}
		inline void _increment(ReverseFalse)
		{
			this->base_reference() += stride1();
			if(++index1() >= (int) size1())
			{
				index1() = 0;
				this->base_reference() -= size1() * stride1();
				_increment_minor(mpl::bool_<Synch>());
			}
		}
			
		void increment_minor()
		{	_increment_minor(mpl::bool_<Synch>());	}
		
		inline void _increment_minor(SynchTrue)
		{
			++index2();
			this->base_reference() += stride2();
		}
		inline void _increment_minor(SynchFalse)
		{	_decrement_minor(SynchTrue());	}
		
		
		void decrement()	//equivalent to index1()--, but with proper side effects
		{	_decrement(mpl::bool_<Reverse>());	}
		
		inline void _decrement(ReverseTrue)	{	_increment(ReverseFalse());	}
		inline void _decrement(ReverseFalse)
		{
			this->base_reference() -= stride1();
			if(--index1() < 0)
			{
				index1() = size1() - 1;
				this->base_reference() += size1() * stride1();
				_decrement_minor(mpl::bool_<Synch>());
			}
		}
			
		void decrement_minor()
		{	_decrement_minor(mpl::bool_<Synch>());	}
		
		inline void _decrement_minor(SynchTrue)
		{
			--index2();
			this->base_reference() -= stride2();
		}
		inline void _decrement_minor(SynchFalse)
		{	_increment_minor(SynchTrue());	}
		
		void advance(int n)
		{	_advance(n, mpl::bool_<Reverse>());	}
		
		inline void _advance(int n, ReverseTrue)
		{	_advance(-n, ReverseFalse());	}
		inline void _advance(int n, ReverseFalse)
		{
			index1() += n;
			if(index1() < 0 || index1() >= (int)size1())
			{
				rebound();
				realign();
			}
			else this->base_reference() += n * stride1();
		}
		
		template<typename Iter>
		int distance_to(Iter other) const
		{
			int raw_distance = &(*other) - &(**this);
			
			return movement_for_raw_distance(raw_distance);
		}
		
		int movement_for_raw_distance(int raw_distance)
		{	return _movement_for_raw_distance(raw_distance, mpl::bool_<Reverse>());	}
	
		inline int _movement_for_raw_distance(int raw_distance, ReverseTrue)
		{	return _movement_for_raw_distance(-raw_distance, ReverseFalse());	}
		inline int _movement_for_raw_distance(int raw_distance, ReverseFalse)
		{
			int tmp = x_ + raw_distance;
			int tmp2 = tmp / row_stride_;
			int tmp3 = tmp % row_stride_;
			
			return 1;
		}
		
		int distance_to(const area_iterator& other) const
		{
			return _distance_to(other.index1() - index1(), other.index2() - index2(), 
				mpl::bool_<Reverse>());
		}
		
		inline int _distance_to(int d1, int d2, ReverseTrue) const 
		{	return _distance_to(-d1, -d2, ReverseFalse());	}
		inline int _distance_to(int d1, int d2, ReverseFalse) const
		{	return __distance_to(d1, d2, mpl::bool_<Synch>());	}
		
		inline int __distance_to(int d1, int d2, SynchTrue) const
		{	return d1 + d2 * size1();	}
		inline int __distance_to(int d1, int d2, SynchFalse) const
		{	return __distance_to(d1, -d2, SynchTrue());	}
		
		void realign()
		{	this->base_reference() = start_ + x_ + y_ * row_stride_;	}
		
		void rebound()	{	rebound(mpl::bool_<Reverse>());	}
		inline void rebound(ReverseTrue)
		{
			int adjust = index1() / (int)size1() - (index1() < 0);
			int remainder = index1() % (int) size1() + (-(index1() < 0) & size1());
			
			index1() = remainder;
			adjust_minor(adjust, mpl::bool_<Synch>());
		}
		inline void rebound(ReverseFalse)
		{
			int adjust = index1() / (int)size1() - (index1() < 0);
			int remainder = index1() % (int)size1() + (-(index1() < 0) & size1());
			
			index1() = remainder;
			adjust_minor(adjust, mpl::bool_<Synch>());
		}
		inline void adjust_minor(int n, SynchTrue)
		{	index2() += n;	}
		inline void adjust_minor(int n, SynchFalse)
		{	index2() -= n;	}
			
	private:
		std::size_t width_, height_, row_stride_;
		int x_, y_;
		typename area_iterator::base_type start_;
};

typedef area_iterator<false, true, true, false> iterator;
typedef area_iterator<true, true, true, false> const_iterator;

typedef area_iterator<false, false, true, false> vertical_iterator;
typedef area_iterator<true, false, true, false> const_vertical_iterator;

typedef area_iterator<false, true, false, false> flipped_iterator;
typedef area_iterator<true, true, false, false> const_flipped_iterator;

typedef area_iterator<false, true, true, true> reverse_iterator;
typedef area_iterator<true, true, true, true> const_reverse_iterator;


iterator begin()	
{	return iterator(storage_.begin(), width_, height_, row_stride_);	}
const_iterator begin() const
{	return const_iterator(storage_.begin(), width_, height_, row_stride_);	}

iterator begin_area(int x, int y, std::size_t width, std::size_t height)
{	
	assert(0 <= x && x + width <= width_);
	assert(0 <= y && y + height <= height_);
	
	return iterator(storage_.begin() + x + y * row_stride_, width, height, row_stride_);
}
const_iterator begin_area(int x, int y, std::size_t width, std::size_t height) const
{	
	assert(0 <= x && x + width <= width_);
	assert(0 <= y && y + height <= height_);
	
	return const_iterator(storage_.begin() + x + y * row_stride_, width, height, row_stride_);
}

vertical_iterator begin_vertical()
{	return vertical_iterator(storage_.begin(), width_, height_, row_stride_);	}
const vertical_iterator begin_vertical() const
{	
	return const_vertical_iterator(storage_.begin(), width_, height_, row_stride_);
}

flipped_iterator begin_flipped()
{
	return flipped_iterator(storage_.begin(), width_, height_, 
		row_stride_, 0, height_ - 1);
}
const_flipped_iterator begin_flipped() const
{
	return const_flipped_iterator(storage_.begin(), width_, height_, 
		row_stride_, 0, height_ - 1);
}

reverse_iterator begin_reverse()
{
	return reverse_iterator(storage_.begin(), width_, height_, row_stride_, 
		width_ - 1, height_ - 1);
}
const_reverse_iterator begin_reverse() const
{
	return const_reverse_iterator(storage_.begin(), width_, height_, row_stride_, 
		width_ - 1, height_ - 1);
}

iterator end()
{	return iterator(storage_.begin(), width_, height_, row_stride_, 0, height_);	}
const_iterator end() const
{	return iterator(storage_.begin(), width_, height_, row_stride_, 0, height_);	}
iterator end_area(int x, int y, std::size_t width, std::size_t height)
{	
	assert(0 <= x && x + width <= width_);
	assert(0 <= y && y + height <= height_);
	
	return iterator(storage_.begin() + x + y * row_stride_, width, height, 
			row_stride_, 0, height);
}
const_iterator end_area(int x, int y, std::size_t width, std::size_t height) const
{	
	assert(0 <= x && x + width <= width_);
	assert(0 <= y && y + height <= height_);
	
	return iterator(storage_.begin() + x + y * row_stride_, width, height, 
		row_stride_, 0, height);
}

vertical_iterator end_vertical()
{	
	return vertical_iterator(storage_.begin(), width_, height_, row_stride_,
		width_, 0);	
}
const vertical_iterator end_vertical() const
{	
	return const_vertical_iterator(storage_.begin(), width_, height_, row_stride_,
		width_, 0);
}

flipped_iterator end_flipped()
{
	return flipped_iterator(storage_.begin(), width_, height_, 
		row_stride_, 0, -1);
}
const_flipped_iterator end_flipped() const
{
	return const_flipped_iterator(storage_.begin(), width_, height_, 
		row_stride_, 0, -1);
}

reverse_iterator end_reverse()
{
	return reverse_iterator(storage_.begin(), width_, height_, row_stride_, 
		width_ -1, -1);
}
const_reverse_iterator end_reverse() const
{
	return const_reverse_iterator(storage_.begin(), width_, height_, row_stride_, 
		width_ - 1, -1);
}	
	
	
template<bool Constant>
class any_area_iterator_ : public boost::iterator_facade<
	any_area_iterator_<Constant>, const Element, boost::random_access_traversal_tag>
{
	public:
		typedef typename area_iterator<Constant, true, true, true>::reference_type 
			reference_type;
			
		template<bool Major, bool Synch, bool Reverse>
		any_area_iterator_(const area_iterator<Constant, Major, Synch, Reverse>& iter)
			:	holder_(new holder<Major, Synch, Reverse>(iter))
		{}
		
		any_area_iterator_(const any_area_iterator_& other)
			:	holder_(other.holder_->clone())
		{}
		
		void transpose()
		{	holder_.reset(holder_->transpose());	}
		
		void flip()
		{	holder_.reset(holder_->flip());	}
		
		void reverse()
		{	holder_.reset(holder_->reverse());	}
		
	private:
		void increment()
		{	holder_->increment();	}
		
		void decrement()
		{	holder_->decrement();	}
		
		void advance(int n)
		{	holder_->advance(n);	}
		
//		template<typename Iter>
//		int distance_to(Iter other) const
//		{	return holder_->distance_to(other);	}
		
//		template<typename Iter>
//		bool equal(const Iter& other) const
//		{	return holder_->equal(other);		}
		
		class placeholder
		{
			public:
				~placeholder();
				
				virtual reference_type *dereference() const = 0;
				virtual void increment() = 0;
				virtual void decrement() = 0;
				virtual void advance(int n) = 0;
				
		//		virtual bool equal(Iter iter) const = 0;
				
		//		virtual int distance_to(Iter iter) const = 0;
				
				virtual placeholder *clone() const = 0;
				
				virtual placeholder* transpose() = 0;
				virtual placeholder* flip() = 0;
				virtual placeholder* reverse() = 0;
				
				virtual bool isRowMajor() const = 0;
		};
		
		template<bool Major, bool Synch, bool Reverse>
		class holder : public placeholder
		{
			public:
				holder(const area_iterator<Constant, Major, Synch, Reverse>& iter) 
					: iter_(iter) {}
					
					reference_type dereference()	{	return *iter_;	}
					void increment()	{	iter_++;	}
					void decrement()	{	iter_--;	}
					void advance(int n)	{	iter_ += n;	}
					
					template<typename Iter>
					int distance_to(const Iter& other)
					{	return other - iter_;	}
					
					template<typename Iter>
					bool equal(const Iter& other)
					{	return iter_ == other;	}
					
					placeholder* clone() const	
					{	return new holder<Major, Synch, Reverse>(*this);	}
					
					placeholder* transpose()
					{	
						return new holder<!Major, Synch, Reverse>(
							iter_.transpose());
					}
					
					placeholder* flip()
					{
						return new holder<Major, !Synch, Reverse>(
							iter_.flip());
					}
					
					placeholder* reverse() 
					{
						return new holder<Major, Synch, !Reverse>(
							iter_.reverse());
					}
					
			private:
				area_iterator<Constant, Major, Synch, Reverse> iter_;
		};
		
		std::auto_ptr<placeholder> holder_;
};	